Python: Make encrypted reasoning opt-in for Foundry chat - #7536
Python: Make encrypted reasoning opt-in for Foundry chat#7536Evan Mattson (moonbox3) wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adjusts the Python Foundry chat client so encrypted reasoning (reasoning.encrypted_content) is no longer implicitly requested, avoiding 400 failures on Foundry deployments/models that don’t support it, while still allowing callers to explicitly opt in.
Changes:
- Override
FoundryChatClientoption preparation to strip framework-injectedreasoning.encrypted_contentunless the caller explicitly requested it. - Add regression tests covering default behavior (no encrypted reasoning) and explicit opt-in preservation.
- Document the Foundry encrypted-reasoning opt-in rule in the Python function-calling loop specification.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| python/packages/foundry/agent_framework_foundry/_chat_client.py | Removes implicit encrypted-reasoning include for Foundry chat requests unless explicitly requested by the caller. |
| python/packages/foundry/tests/foundry/test_foundry_chat_client.py | Adds tests validating default omission and explicit opt-in forwarding of reasoning.encrypted_content. |
| docs/specs/004-python-function-calling-loop.md | Records the Foundry-specific rule and links the relevant regression tests. |
There was a problem hiding this comment.
Agent Framework Skill Review
Completed passes: 5 | Failed passes: 0 | Confidence: 59% | Result: No high-severity findings
Review passes
- Correctness (
gpt-5.6-sol) — No high-confidence issues found in this pass. - Security Reliability (
claude-opus-4.8) — No high-confidence issues found in this pass. - Test Coverage (
gpt-5.6-sol) — The new tests do not cover preservation of unrelated include values after filtering, so a regression that removes all caller-suplied includes could pass unnoticed. - Failure Modes (
claude-opus-4.8) — No high-confidence issues found in this pass. - Design Approach (
claude-opus-4.8) — No high-confidence issues found in this pass.
No high-severity findings survived the review and verification pipeline.
PR ensemble review by moonbox3's agents
Python Test Coverage Report •
Python Unit Test Overview
|
||||||||||||||||||||||||||||||
|
/review |
There was a problem hiding this comment.
Agent Framework Review — Iteration 2
Completed passes: 5 | Failed passes: 0 | Result: No high-severity findings
Scope: 1 net-new commit(s): 71e71dce562d
Review passes
- Correctness (
gpt-5.6-sol) — No high-confidence issues found in this pass. - Security Reliability (
claude-opus-4.8) — No high-confidence issues found in this pass. - Test Coverage (
gpt-5.6-sol) — No high-confidence issues found in this pass. - Failure Modes (
claude-opus-4.8) — No high-confidence issues found in this pass. - Design Approach (
claude-opus-4.8) — No high-confidence issues found in this pass.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (3)
python/packages/foundry/agent_framework_foundry/_chat_client.py:271
- The removal logic only runs when
run_options['include']is alist. If upstream returns (or a middleware sets)includeas a tuple/sequence, the framework-injectedreasoning.encrypted_contentwon’t be stripped and Foundry deployments may still 400. Consider handling broader iterables (e.g.,Sequence[str]) by normalizingincludeto a list before filtering, and only emittingincludewhen non-empty.
@override
async def _prepare_options(
self,
messages: Sequence[Message],
options: Mapping[str, Any],
) -> dict[str, Any]:
"""Prepare Foundry options without implicitly requesting encrypted reasoning."""
caller_requested_encrypted_reasoning = "reasoning.encrypted_content" in (options.get("include") or [])
run_options = await super()._prepare_options(messages, options)
if not caller_requested_encrypted_reasoning and isinstance(run_options.get("include"), list):
include = [item for item in run_options["include"] if item != "reasoning.encrypted_content"]
if include:
run_options["include"] = include
else:
run_options.pop("include")
return run_options
python/packages/foundry/tests/foundry/test_foundry_chat_client.py:461
- These tests validate presence/absence of the encrypted include value, but they don’t assert the stronger behavior implemented in
_prepare_options: when the only included item is the framework-added encrypted reasoning, theincludefield is removed entirely (not sent asinclude=[]). Consider asserting on the actual kwargs passed towith_raw_response.create(e.g., by inspectingcall_args.kwargs) to ensure theincludekey is omitted when appropriate.
async def create_response(**kwargs: Any) -> Any:
if "reasoning.encrypted_content" in kwargs.get("include", []):
raise ValueError("Encrypted content is not supported with this model.")
return _as_raw(mock_response)
python/packages/foundry_hosting/tests/test_responses_int.py:629
- Adding
include: ['reasoning.encrypted_content']at this shareddefault_optionsconstruction site can change the behavior of any tests that reuse this boundary/server setup. If only specific replay scenarios require encrypted reasoning, it would be less coupling to scope the opt-in to the smallest possible test surface (e.g., set it only for the specific test/agent instance that needs it), or add a short comment here explaining why all consumers of this helper must opt in.
default_options={ # pyrefly: ignore[bad-argument-type]
"store": False,
"reasoning": {"effort": "low", "summary": "auto"},
"include": ["reasoning.encrypted_content"],
},
)
server = ResponsesHostServer(agent, store=InMemoryResponseProvider())
Motivation & Context
FoundryChatClientinherits stateless OpenAI Responses behavior that automatically requests encrypted reasoning content. Foundry deployments such as GPT-4.1 reject that include value, causing otherwise ordinary chat requests to fail with a 400 response. Encrypted reasoning therefore needs to be controlled by the caller for Foundry deployments with different model capabilities.Important
For reasoning models, encrypted reasoning content is opt-in. To request it, configure
includein the agent's default options:Description & Review Guide
reasoning.encrypted_contentinclude value, while preserving an explicit caller opt-in. Add public-seam regression tests for both paths and record the provider rule in the function-loop specification.Related Issue
Fixes #7483
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.